package project.layer.agents;

import java.util.ArrayList;

import project.layer.ant.IntentionAnt;
import project.layer.ant.SearchingExplorationAnt;
import project.layer.physical.Crossroad;
import project.layer.physical.Path;
import project.layer.physical.Road;
import project.layer.physical.Truck;
import project.layer.physical.commands.LeaveCrossroadCommand;
import project.testenvironment.TestingParameters;

public class TruckAgentStatePickingUpPackage extends TruckAgentState {

	
	private int hopsSinceLastExploration = 0;
	private boolean shouldReExplore = false;
	private int currentExplorationAntHopcount = getInitialExplorationAntMaxHopCount();
	private int ticksLeftTillExploration = 1;
	private int currentNbOfPNDSequences = getStartingNbOfPNDSequences();

	
	public TruckAgentStatePickingUpPackage(TruckAgent tAgent){
		super(tAgent);
	}
	
	public static final int getInitialExplorationAntMaxHopCount(){
		return TestingParameters.EXPLORATION_ANT_INITIAL_MAX_HOPS;
	}
	
	public static final int getExplorationTurnoverCount(){
		return TestingParameters.EXPLORATION_ANT_EXPLORATION_TURNOVER_COUNT;
	}
	
	
	public static final int getStartingNbOfPNDSequences(){
		return TestingParameters.NB_OF_PND_SEQUENCES;
	}
	
	
	public static final int getExplorationAntHopCountIncrease(){
		return TestingParameters.EXPLORATION_ANT_HOP_COUNT_INCREASE;
	}
	
	public static final int getMaxExplorationAntMaxHopCount(){
		return TestingParameters.EXPLORATION_ANT_MAX_HOP_COUNT_MAX;
	}
	
	public static final int getAmountOfHopsTillReexploration(){
		return TestingParameters.AMOUNT_OF_HOPS_TILL_REEXPLORATION;
	}
	
	private void resetNbOfSequencesToDefault(){
		this.currentNbOfPNDSequences = getStartingNbOfPNDSequences();
	}
	
	private void resetReexploration(){
		this.hopsSinceLastExploration = getAmountOfHopsTillReexploration();
	}
	
	@Override
	public void processTruckTick() {
		if(!getTruckAgent().getTruck().isOnConnector() || !getTruckAgent().getTruck().allCommandsProcessed()){
			driveTillNextCrossroad();
		}
		else{
			if(getTruckAgent().hasIntention()){
				renewIntention();
				
			}
			
			if(getTruckAgent().hasIntention()){
//				if(shouldReExplore){
//					searchForNewIntention();
//					shouldReExplore = false;
//				}
//				else{
					executeIntention();
//				}
				
			}else{
				if(getTruckAgent().hasDesires()){
					
					evaluateDesires();
				}
				else{
					ticksLeftTillExploration--;
					if(ticksLeftTillExploration == 0 ){
						searchForNewIntention();
						ticksLeftTillExploration = getExplorationTurnoverCount();
					}
				}
			}
			
			
			
			
			
			
		}
		

	}
	
	private void evaluateDesires() {
		resetReexploration();
		ArrayList<Path> desires = getTruckAgent().getDesires();

		Path optimalDesire = getShortestDesire(desires);
		if(getTruckAgent().hasIntention()){
			if(optimalDesire.getTotalDistance() < getTruckAgent().getIntention().getTotalDistance() ){
				IntentionAnt iAnt = new IntentionAnt(getTruckAgent(), getTruckAgent().getTruck().getConnectorPosition().getConnector(), optimalDesire);
			}
		}
		else{
			new IntentionAnt(getTruckAgent(), getTruckAgent().getTruck().getConnectorPosition().getConnector(), optimalDesire);
		}

		getTruckAgent().clearDesires();
		resetExplorationMaxHopCount();
		resetNbOfSequencesToDefault();
	}
	
	

	private Path getShortestDesire(ArrayList<Path> desires) {
		Path result = desires.get(0);
		for(int i = 1; i < desires.size(); i++){
			Path cPath = desires.get(i);
			if(cPath.getDistanceToLastPickupPoint() < result.getDistanceToLastPickupPoint()){
				result = cPath;
			}
		}
		return result;
	}

	private void executeIntention() {

		getTruckAgent().clearDesires();
		hopsSinceLastExploration++;
		if(hopsSinceLastExploration == getAmountOfHopsTillReexploration()){
			shouldReExplore = true;
			hopsSinceLastExploration = 0;
		}
		
		
		Crossroad currentCrossroad = getTruckAgent().getTruck().getConnectorPosition().getConnector();
		
		if(currentCrossroad.hasPickUpPoint() && currentCrossroad.getPickUpPoint().getCorrespondingAgent().getId() == getTruckAgent().getIntention().getDestinations().getFirst()){
			getTruckAgent().getTruck().pickUpPackage();
		
			getTruckAgent().removeVisitedDestinationFromIntention(currentCrossroad.getPickUpPoint().getCorrespondingAgent().getId());
			getTruckAgent().switchToDeliveringState();
			
		}
		else{
			Crossroad nextCrossroad = getTruckAgent().getIntention().getFollowingCrossroad(currentCrossroad);
			Road roadToBeTaken = currentCrossroad.getConnectionTo(nextCrossroad);
			if(roadToBeTaken != null){
				LeaveCrossroadCommand cmd = new LeaveCrossroadCommand(getTruckAgent().getTruck(), roadToBeTaken);
				getTruckAgent().getTruck().addCommand(cmd, getTruckAgent());
			}
			else{
				System.out.println(currentCrossroad.getId());
				System.out.println(nextCrossroad.getId());
			}
			getTruckAgent().removeTakenCrossroadFromIntention();
		}
		
		
		
	}

	private void searchForNewIntention() {
		resetReexploration();
		Truck truck = getTruckAgent().getTruck();
		SearchingExplorationAnt explAnt = new SearchingExplorationAnt(getTruckAgent(), truck.getConnectorPosition().getConnector(), getCurrentExplorationAntHopcount(), getCurrentNbOfPNDSequences());
		currentExplorationAntHopcount += getExplorationAntHopCountIncrease();
		if(currentExplorationAntHopcount > getMaxExplorationAntMaxHopCount()){
			currentExplorationAntHopcount = getInitialExplorationAntMaxHopCount();
		}
		if(getCurrentNbOfPNDSequences() != 1){
			currentNbOfPNDSequences--;
		}
		
		
		
	}
	
	@Override
	public void resetExplorationMaxHopCount(){
		currentExplorationAntHopcount = getInitialExplorationAntMaxHopCount();
	}

	@Override
	public boolean isPickingUpPackage(){
		return true;
	}

	public int getCurrentExplorationAntHopcount() {
		return currentExplorationAntHopcount;
	}

	public int getCurrentNbOfPNDSequences() {
		return currentNbOfPNDSequences;
	}

}
